package service

import (
	"encoding/json"
	"errors"
	"fmt"
	ClickHouse "gin/database"
	"gin/model"
	"gin/types"
	"github.com/gin-gonic/gin"
	teamones_helper "github.com/teamones-open/go-helper"
	"time"
)

type User struct {
}

type DepartmentUser struct {
	DepartmentId uint64 `json:"department_id"`
	UserId       uint64 `json:"user_id"`
	UserName     string `json:"user_name"`
	RoleName     string `json:"role_name"`
	TenantId     uint64 `json:"tenant_id"`
	UnionId      uint64 `json:"union_id"`
	TenantName   string `json:"tenant_name"`
}

type TenantUser struct {
	UserId uint64 `json:"user_id"`
	RoleId uint64 `json:"role_id"`
}

// 获取指定租户内部用户指定时间范围的工时排行榜
func (c User) getUserManHourRank(TenantId uint64) {

}

// 获取部门下面用户列表
func (c User) GetDepartmentUser(departmentIds []int64, tenantId uint64) (DepartmentUsers map[uint64][]DepartmentListCount, DistinctUserIds []uint64, err error) {
	var departmentUsers []DepartmentUser
	dbr := ClickHouse.DB.Model(&model.TenantUser{})
	dbr.Joins("LEFT JOIN user on user.union_id = tenant_user.user_id").
		Joins("LEFT JOIN role on role.id = tenant_user.role_id").
		Where("tenant_user.tenant_id = ?", tenantId).
		Where("tenant_user.status = ?", "active").
		Where("tenant_user.department_id in (?) ", departmentIds).
		Select("tenant_user.department_id as department_id,tenant_user.user_id as user_id,role.name as role_name,user.name as user_name").
		Find(&departmentUsers)

	if dbr.Error != nil {
		err = dbr.Error
		return
	}

	// 获取用户对应角色字典
	var UserRolesMap = make(map[uint64][]interface{})
	for _, UserItem := range departmentUsers {
		if !teamones_helper.InArray(UserItem.RoleName, UserRolesMap[UserItem.UserId]) {
			UserRolesMap[UserItem.UserId] = append(UserRolesMap[UserItem.UserId], UserItem.RoleName)
		}
	}

	// 获取部门对应用户字典
	var userRoleItem DepartmentListCount
	var DepartmentUsersMap = make(map[uint64][]DepartmentListCount)

	// 返回去重的用户ids列表
	var handleUserIds = make(map[uint64][]string)
	for _, DepartmentItem := range departmentUsers {
		if _, ok := handleUserIds[DepartmentItem.UserId]; !ok {
			//不存在
			handleUserIds[DepartmentItem.UserId] = append(handleUserIds[DepartmentItem.UserId], "ok")
			DistinctUserIds = append(DistinctUserIds, DepartmentItem.UserId)

			// 当前用户信息
			userRoleItem.Id = 0
			userRoleItem.UserId = DepartmentItem.UserId
			userRoleItem.Name = DepartmentItem.UserName
			userRoleItem.Type = "user"
			userRoleItem.ParentId = DepartmentItem.DepartmentId
			userRoleItem.TenantId = int64(tenantId)

			userRoleItem.Roles = UserRolesMap[DepartmentItem.UserId]
			DepartmentUsersMap[uint64(DepartmentItem.DepartmentId)] = append(DepartmentUsersMap[uint64(DepartmentItem.DepartmentId)], userRoleItem)
		}
	}
	DepartmentUsers = DepartmentUsersMap
	return
}

// GetDepartmentUserMultiDepartmentUser 获取部门下面用户列表
func (c User) GetDepartmentUserMultiDepartmentUser(departmentIds []uint64, tenantId int64) (DepartmentUsers []DepartmentUser, DistinctUserIds []uint64, err error) {
	if len(departmentIds) == 0 {
		return
	}
	err = ClickHouse.DB.Model(&model.User{}).
		Joins("LEFT JOIN im_user on user.union_id = im_user.id").
		Joins("LEFT JOIN tenant_user on user.union_id = tenant_user.user_id").
		Joins("LEFT JOIN role on role.id = tenant_user.role_id").
		Joins("LEFT JOIN tenant on tenant_user.tenant_id = tenant.id").
		Where("im_user.active = ?", 1).
		Where("tenant_user.tenant_id = ?", tenantId).
		Where("tenant_user.status = ?", "active").
		Where("tenant_user.department_id in (?) ", departmentIds).
		Select("tenant_user.user_id as union_id,tenant_user.department_id as department_id,user.id as user_id," +
			"role.name as role_name,user.name as user_name,tenant_user.tenant_id as tenant_id,tenant.name as tenant_name").
		Find(&DepartmentUsers).Error

	if err != nil {
		return
	}

	var distinctUserMap = make(map[uint64]uint64, 0)
	for _, user := range DepartmentUsers {
		if _, ok := distinctUserMap[user.UserId]; !ok {
			distinctUserMap[user.UserId] = user.UserId
			DistinctUserIds = append(DistinctUserIds, user.UserId)
		}
	}

	return
}

// GetDepartmentUserMultiTenantIdDepartmentUser 获取部门下面用户列表
func (c User) GetDepartmentUserMultiTenantIdDepartmentUser(departmentIds []uint64, tenantIds []uint64) (DepartmentUsers []DepartmentUser, DistinctUserIds []uint64, err error) {
	if len(departmentIds) == 0 {
		return
	}
	err = ClickHouse.DB.Model(&model.User{}).
		Joins("LEFT JOIN im_user on user.union_id = im_user.id").
		Joins("LEFT JOIN tenant_user on user.union_id = tenant_user.user_id").
		Joins("LEFT JOIN role on role.id = tenant_user.role_id").
		Where("im_user.active = ?", 1).
		Where("tenant_user.tenant_id IN ?", tenantIds).
		Where("tenant_user.status = ?", "active").
		Where("tenant_user.department_id in (?) ", departmentIds).
		Select("tenant_user.department_id as department_id,user.id as user_id,role.name as role_name,user.name as user_name,tenant_user.tenant_id as tenant_id").
		Find(&DepartmentUsers).Error

	if err != nil {
		return
	}

	var distinctUserMap = make(map[string]uint64, 0)
	for _, user := range DepartmentUsers {
		key := fmt.Sprintf("%d_%d", user.UserId, user.TenantId)
		if _, ok := distinctUserMap[key]; !ok {
			distinctUserMap[key] = user.UserId
			DistinctUserIds = append(DistinctUserIds, user.UserId)
		}
	}
	return
}

// 通过角色Code获取用户列表
func (c User) GetUserListByRoleCode(tenantId int64, roleCode []string) (UserIds []uint64, err error) {
	var tenantUser []TenantUser
	err = ClickHouse.DB.Model(&model.TenantUser{}).
		Joins("LEFT JOIN role on role.id = tenant_user.role_id").
		Where("role.code in ?", roleCode).
		Where("tenant_user.tenant_id = ?", tenantId).
		Where("tenant_user.status = ?", "active").
		Distinct("user_id").
		Find(&tenantUser).Error

	if err != nil {
		return
	}

	for _, user := range tenantUser {
		UserIds = append(UserIds, user.UserId)
	}

	return
}

// GetSaasUserIdByUnionId 通过im user_id 获取 saas user id
func GetSaasUserIdByUnionId(imUserId int64) (res int64, err error) {

	rk := fmt.Sprintf("user:GetSaasUserIdByUnionId-%d", imUserId)
	val, _ := ClickHouse.Rdb.Get(rk).Result()
	if val != "" {
		err = json.Unmarshal([]byte(val), &res)
		if err == nil {
			return res, err
		}
	}
	err = ClickHouse.DB.Model(&model.User{}).
		Where("union_id = ?", imUserId).
		Pluck("id", &res).Error
	if res == 0 {
		err = errors.New("user not found")
	}

	rs, err := json.Marshal(res)
	if err != nil {
		return res, err
	}
	_, err = ClickHouse.Rdb.Set(rk, rs, time.Minute*60).Result()
	if err != nil {
		return res, err
	}
	return
}

// GetUnionIdByUserId 通过saas user_id 获取 im  user_id
func (c *User) GetUnionIdByUserId(userId int64) (res int64, err error) {

	err = ClickHouse.DB.Model(&model.User{}).
		Where("id = ?", userId).
		Pluck("union_id", &res).Error
	if res == 0 {
		err = errors.New("user not found")
	}
	return
}

// 通过saas user_id 获取 im user_id
func (c User) GetUnionIdListByUserIdList(saasUserIdList []uint64) (imUserIdList []uint64, err error) {
	err = ClickHouse.DB.Model(&model.User{}).
		Where("id in ?", saasUserIdList).
		Pluck("union_id", &imUserIdList).Error

	return
}

// GetUserList 查询用户列表
func (c *User) GetUserList(where interface{}) (res []model.User, err error) {
	err = ClickHouse.DB.Model(&model.User{}).Where(where).Find(&res).Error
	return
}

// GetUserList 查询用户列表带分页
func (c *User) GetUserListPage(where interface{}, page []int) (res []model.User, err error) {
	err = ClickHouse.DB.Model(&model.User{}).Where(where).Offset((page[0] - 1) * page[1]).Limit(page[1]).Find(&res).Error
	return
}

// GetUserList 查询用户列表
func (c *User) GetUserListWithDepartmentId(tenantId int64, where interface{}) (res []types.UserWithDepartmentId, err error) {
	err = ClickHouse.DB.Model(&model.User{}).
		Joins("LEFT JOIN tenant_user on user.union_id = tenant_user.user_id").
		Where("tenant_id = ?", tenantId).
		Where(where).Select("user.*,tenant_user.department_id as department_id").Find(&res).Error
	return
}

// GetUserMapWithTwoLevelDepartment 查询用户列表两层部门
func (c *User) GetUserMapWithTwoLevelDepartment(tenantId int64, where interface{}) (res map[uint64]types.UserListWithTwoLevelDepartment, err error) {
	var resList []types.UserListWithTwoLevelDepartment
	err = ClickHouse.DB.Model(&model.User{}).
		Joins("LEFT JOIN tenant_user on user.union_id = tenant_user.user_id").
		Joins("LEFT JOIN department on tenant_user.department_id = department.id").
		Joins("LEFT JOIN department d_parent on d_parent.id = department.parent_id").
		Where("tenant_user.tenant_id = ?", tenantId).Where(where).
		Select("user.id as id,user.name as name,user.union_id as union_id,user.phone as phone,user.email as email,user.created as created" +
			",department.id AS department_id,department.name AS department_name" +
			",d_parent.id as department_parent_id,d_parent.name as department_parent_name").
		Find(&resList).Error
	if err != nil {
		return
	}
	res = make(map[uint64]types.UserListWithTwoLevelDepartment, 0)
	for _, re := range resList {
		res[re.Id] = re
	}
	return
}

// GetMyUserInfo 读取用户信息
func (c *User) GetMyUserInfo(ctx *gin.Context) (res types.GetMyUserInfoRes, err error) {
	var req = types.GetMyUserInfoReq{}
	var headers = map[string]string{"x-userinfo": GetStringFromContext(ctx, "x-userinfo")}
	err = tr.Do("teamones-im", "user/get_my_user_info", req, headers, &res)
	return
}

// GetOtherUserInfo 读取用户信息
func (c *User) GetOtherUserInfo(ctx *gin.Context, UserId int64) (res types.GetMyUserInfoRes, err error) {
	var req = types.GetOtherUserInfoReq{}
	req.UserId = UserId
	var headers = map[string]string{"x-userinfo": GetStringFromContext(ctx, "x-userinfo")}
	err = tr.Do("teamones-im", "user/get_other_user_info", req, headers, &res)
	return
}

//ByDepartmentOrRoleSelectUser 通过部门或者角色查询用户
func (c User) ByDepartmentOrRoleSelectUser(departmentIds []uint64, roleCode []string, tenantId []int64, userId []int64) (res []model.User, err error) {
	if len(departmentIds) == 0 && len(roleCode) == 0 {
		return
	}
	db := ClickHouse.DB.Model(&model.User{}).
		Joins("LEFT JOIN im_user on user.union_id = im_user.id").
		Joins("LEFT JOIN tenant_user on user.union_id = tenant_user.user_id").
		Joins("LEFT JOIN role on role.id = tenant_user.role_id").
		Where("im_user.active = ?", 1)

	if len(departmentIds) > 0 {
		db = db.Where("tenant_user.department_id in (?) ", departmentIds)
	}

	if len(roleCode) > 0 {
		db = db.Where("role.code in (?) ", roleCode)
	}

	if len(tenantId) > 0 {
		db = db.Where("tenant_user.tenant_id in (?) ", tenantId)
	}

	if len(userId) > 0 {
		db = db.Where("tenant_user.user_id in (?) ", userId)
	}

	var userList []model.User
	err = db.
		Select("user.id as id,user.name as name,user.union_id as union_id").
		Find(&userList).Error

	// 去重
	userMap := map[int64]bool{}
	for _, userItem := range userList {
		if ok := userMap[int64(userItem.Id)]; !ok {
			userMap[int64(userItem.Id)] = true
			res = append(res, userItem)
		}
	}

	return
}
